/*
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "device/csr.h"
#include "device/driver.h"
#include "discovery/csr_utils.h"
#include <iomanip>
#include <map>
#include <mc/expr/function/call.h>
#include <mc/expr/function/collection.h>
#include <mc/expr/function/parser.h>
#include <mc/format.h>
#include <mc/json.h>
#include <mc/log.h>
#include <regex>
#include <set>
#include <sstream>

using namespace mc::expr;

namespace devmon {

device_driver& unit::load_compatible_driver() {
    std::string driver_name;

    for (auto& item : m_compatible) {
        driver_name = item;
        std::replace(driver_name.begin(), driver_name.end(), ',', '_');
        try {
            device_driver& driver =
                device_driver_factory::get_instance().get_device_driver(driver_name);
            return driver;
        } catch (const mc::invalid_arg_exception& e) {
            elog("load compatible driver ${name} failed, error: ${error}",
                 ("name", driver_name)("error", e.what()));
            continue;
        }
    }
    MC_THROW(mc::parse_error_exception, "Driver not found: ${name}", ("name", driver_name));
}

void unit::validate_unit() {
    if (m_type.empty()) {
        MC_THROW(mc::parse_error_exception, "CSR Unit Type is empty");
    }

    if (m_name.empty()) {
        MC_THROW(mc::parse_error_exception, "CSR Unit Name is empty");
    }

    if (m_compatible.empty()) {
        MC_THROW(mc::parse_error_exception, "CSR Unit Compatible is empty");
    }
}

void connector::validate_connector() {
    if (m_position == "") {
        MC_THROW(mc::parse_error_exception, "Connector Position is not initialized");
    }

    if (m_slot == 0) {
        MC_THROW(mc::parse_error_exception, "Connector Slot is not initialized");
    }
}

void device_csr::validate_csr() {
    m_unit.validate_unit();
    if (m_objects.empty()) {
        MC_THROW(mc::parse_error_exception, "CSR Objects is empty");
    }
    m_connector.validate_connector();
}

mc::dict device_csr::process_topology_object() {
    if (!m_topology.contains("Anchor")) {
        m_topology_json = "{}";
        return mc::dict{{"topology", mc::variant(m_topology)},
                        {"objects", mc::variant(mc::mutable_dict{})},
                        {"json_str", mc::variant(std::string("{}"))}};
    }

    // 建立总线名称映射（模板总线名 -> connector总线名）
    auto bus_mapping = build_bus_mapping();
    if (bus_mapping.empty()) {
        m_topology_json = "{}";
        return mc::dict{{"topology", mc::variant(m_topology)},
                        {"objects", mc::variant(mc::mutable_dict{})},
                        {"json_str", mc::variant(std::string("{}"))}};
    }

    // 收集所有需要重命名的对象名称（总线除外）
    auto object_name_mapping = collect_and_create_object_mapping(bus_mapping);

    // 从 m_objects 中提取对应的对象并重命名
    auto extracted_objects = extract_and_rename_objects(object_name_mapping);

    // 转换拓扑为简化格式并重命名
    auto simplified_topology =
        convert_topology_to_simplified_format(bus_mapping, object_name_mapping);

    mc::dict result{
        {"topology", mc::variant(simplified_topology)},
        {"objects", mc::variant(extracted_objects)},
    };

    ilog("Processing completed: ${topo_count} topology nodes, ${obj_count} objects",
         ("topo_count", simplified_topology.size())("obj_count", extracted_objects.size()));

    return result;
}

std::map<std::string, std::string> device_csr::build_bus_mapping() {
    std::map<std::string, std::string> bus_mapping;

    if (!m_topology.contains("Anchor")) {
        return bus_mapping;
    }

    auto         anchor = m_topology["Anchor"];
    mc::variants template_buses;

    // 获取模板总线列表
    if (anchor.is_dict()) {
        auto anchor_dict = anchor.as_dict();
        if (anchor_dict.contains("Buses")) {
            template_buses = anchor_dict["Buses"].as_array();
        }
    } else if (anchor.is_array()) {
        template_buses = anchor.as_array();
    }

    auto connector_buses = m_connector.m_buses;

    // 检查模板总线数量与连接器总线数量是否匹配
    if (template_buses.size() != connector_buses.size()) {
        wlog("Template bus count (${template_count}) does not match connector bus count (${connector_count})",
             ("template_count", template_buses.size())("connector_count", connector_buses.size()));
        return bus_mapping;
    }

    // 创建主总线名称映射表：模板总线名 -> 实际总线名（主总线不加position后缀）
    for (size_t i = 0; i < template_buses.size(); ++i) {
        std::string template_bus_name  = template_buses[i].as<std::string>();
        std::string connector_bus_name = connector_buses[i].as<std::string>();
        bus_mapping[template_bus_name] = connector_bus_name; // 主总线不加position后缀

        ilog("Main bus mapping: ${template} -> ${actual}",
             ("template", template_bus_name)("actual", connector_bus_name));
    }

    return bus_mapping;
}

std::map<std::string, std::string> device_csr::collect_and_create_object_mapping(
    const std::map<std::string, std::string>& bus_mapping) {
    std::set<std::string>              all_object_names;
    std::map<std::string, std::string> object_name_mapping;
    std::string                        position = m_connector.m_position;

    std::set<std::string> topology_node_names;
    for (auto it = m_topology.begin(); it != m_topology.end(); ++it) {
        std::string key = it->key.as_string();
        if (key != "Anchor") {
            topology_node_names.insert(key);
        }
    }

    // 首先处理主总线对象：主总线对象不添加position后缀
    for (const auto& [template_bus_name, actual_bus_name] : bus_mapping) {
        // 检查 m_objects 中是否存在对应的主总线对象
        if (m_objects.contains(template_bus_name)) {
            object_name_mapping[template_bus_name] = actual_bus_name; // 主总线不加position后缀
            all_object_names.insert(template_bus_name);
            ilog("Collecting main bus object: ${template} -> ${actual}",
                 ("template", template_bus_name)("actual", actual_bus_name));
        }
        if (m_objects.contains(actual_bus_name)) {
            object_name_mapping[actual_bus_name] = actual_bus_name; // 主总线不加position后缀
            all_object_names.insert(actual_bus_name);
            ilog("Collecting main bus object: ${name} -> ${name}", ("name", actual_bus_name));
        }
    }

    // 遍历拓扑收集所有器件对象和总线节点名称
    for (auto it = m_topology.begin(); it != m_topology.end(); ++it) {
        std::string key = it->key.as_string();
        if (key == "Anchor") {
            continue;
        }

        // 如果当前键本身是一个总线节点（不是主总线），也需要重命名
        if (bus_mapping.find(key) == bus_mapping.end()) {
            // 不是主总线，检查是否在objects中存在，如果存在则需要重命名
            if (m_objects.contains(key)) {
                all_object_names.insert(key);
                object_name_mapping[key] = key + "_" + position;
                ilog("Collecting bus node object: ${name} -> ${new_name}",
                     ("name", key)("new_name", key + "_" + position));
            }
        }

        auto node_value = it->value;
        if (node_value.is_dict()) {
            auto node_dict = node_value.as_dict();

            // 收集 Chips 中的对象名称
            if (node_dict.contains("Chips")) {
                auto chips = node_dict["Chips"].as_array();
                for (const auto& chip : chips) {
                    if (chip.is_string()) {
                        std::string chip_name = chip.as_string();
                        // 如果不是主总线，就需要添加position后缀
                        if (bus_mapping.find(chip_name) == bus_mapping.end()) {
                            all_object_names.insert(chip_name);
                            object_name_mapping[chip_name] = chip_name + "_" + position;
                            ilog("Collecting device object: ${name} -> ${new_name}",
                                 ("name", chip_name)("new_name", chip_name + "_" + position));
                        }
                    }
                }
            }

            // 收集 Connectors 中的对象名称
            if (node_dict.contains("Connectors")) {
                auto connectors = node_dict["Connectors"].as<mc::variants>();
                for (const auto& connector : connectors) {
                    if (connector.is_string()) {
                        std::string connector_name = connector.as_string();
                        if (bus_mapping.find(connector_name) == bus_mapping.end()) {
                            all_object_names.insert(connector_name);
                            object_name_mapping[connector_name] = connector_name + "_" + position;
                            ilog("Collecting connector object: ${name} -> ${new_name}",
                                 ("name", connector_name)("new_name",
                                                          connector_name + "_" + position));
                        }
                    }
                }
            }
        } else if (node_value.is_array()) {
            auto items = node_value.as_array();
            for (const auto& item : items) {
                if (item.is_string()) {
                    std::string item_name = item.as_string();
                    // 如果不是主总线，就需要添加position后缀
                    if (bus_mapping.find(item_name) == bus_mapping.end()) {
                        all_object_names.insert(item_name);
                        object_name_mapping[item_name] = item_name + "_" + position;
                        ilog("Collecting array item object: ${name} -> ${new_name}",
                             ("name", item_name)("new_name", item_name + "_" + position));
                    }
                }
            }
        }
    }

    ilog("Collected ${count} objects that need renaming", ("count", all_object_names.size()));
    return object_name_mapping;
}

mc::mutable_dict device_csr::extract_and_rename_objects(
    const std::map<std::string, std::string>& object_name_mapping) {
    mc::mutable_dict         extracted_objects;
    std::vector<std::string> objects_to_erase;

    for (const auto& [object_name, new_name] : object_name_mapping) {
        if (m_objects.contains(object_name)) {
            auto object_data            = m_objects[object_name];
            extracted_objects[new_name] = object_data;
            objects_to_erase.push_back(object_name);
            ilog("Extracting object: ${old} -> ${new}", ("old", object_name)("new", new_name));
        }
    }

    // 从 m_objects 中删除已处理的对象
    for (const auto& object_name : objects_to_erase) {
        m_objects.erase(object_name);
    }

    return extracted_objects;
}

mc::mutable_dict device_csr::convert_topology_to_simplified_format(
    const std::map<std::string, std::string>& bus_mapping,
    const std::map<std::string, std::string>& object_name_mapping) {
    mc::mutable_dict simplified_topology;

    if (m_topology.contains("Anchor")) {
        auto         anchor = m_topology["Anchor"];
        mc::variants template_buses;

        if (anchor.is_dict()) {
            auto anchor_dict = anchor.as_dict();
            if (anchor_dict.contains("Buses")) {
                template_buses = anchor_dict["Buses"].as_array();
            }
        } else if (anchor.is_array()) {
            template_buses = anchor.as_array();
        }

        mc::variants new_anchor_buses;
        for (const auto& bus : template_buses) {
            std::string template_name = bus.as_string();
            if (bus_mapping.find(template_name) != bus_mapping.end()) {
                std::string actual_name = bus_mapping.at(template_name);
                new_anchor_buses.emplace_back(actual_name);
            }
        }
        simplified_topology["Anchor"] = new_anchor_buses;
    }

    for (auto it = m_topology.begin(); it != m_topology.end(); ++it) {
        std::string key = it->key.as_string();
        if (key == "Anchor") {
            continue;
        }

        // 获取新的键名
        std::string new_key = key;
        if (bus_mapping.find(key) != bus_mapping.end()) {
            // 主总线名称替换（不加position后缀）
            new_key = bus_mapping.at(key);
        } else if (object_name_mapping.find(key) != object_name_mapping.end()) {
            // 器件对象或总线节点重命名（加position后缀）
            new_key = object_name_mapping.at(key);
        }

        // 转换节点值为简化格式并重命名引用
        auto         node_value = it->value;
        mc::variants simplified_items;

        // 重命名引用
        auto rename_reference = [&](const std::string& original_name) -> std::string {
            auto bus_iter = bus_mapping.find(original_name);
            if (bus_iter != bus_mapping.end()) {
                return bus_iter->second;
            }
            auto object_iter = object_name_mapping.find(original_name);
            if (object_iter != object_name_mapping.end()) {
                return object_iter->second;
            }
            return original_name;
        };

        // 追加项目到简化拓扑
        auto append_items = [&](const mc::variants& source_items) {
            for (const auto& item : source_items) {
                if (item.is_string()) {
                    simplified_items.emplace_back(rename_reference(item.as<std::string>()));
                } else {
                    simplified_items.emplace_back(item);
                }
            }
        };

        if (node_value.is_dict()) {
            auto node_dict = node_value.as_dict();

            // 处理 Chips 字段
            if (node_dict.contains("Chips")) {
                append_items(node_dict["Chips"].as<mc::variants>());
            }
            // 处理 Buses 字段
            if (node_dict.contains("Buses")) {
                append_items(node_dict["Buses"].as<mc::variants>());
            }
            // 处理 Connectors 字段
            if (node_dict.contains("Connectors")) {
                append_items(node_dict["Connectors"].as<mc::variants>());
            }
        } else if (node_value.is_array()) {
            // 如果已经是数组格式，重命名其中的引用
            append_items(node_value.as_array());
        }

        simplified_topology[new_key] = simplified_items;
    }

    return simplified_topology;
}

bool device_csr::is_function_object(const std::string& object_name) {
    return object_name.substr(0, 5) == "Func_";
}

void device_csr::process_objects_placeholders() {
    mc::mutable_dict processed_objects;

    // 占位符映射表：占位符名称 -> 对应的值
    const mc::dict placeholder_map = {
        {"Slot", std::to_string(m_connector.m_slot)},
        {"Position", m_connector.m_position},
        {"SystemId", std::to_string(m_connector.m_system_id)},
        {"GroupPosition", m_connector.m_group_position},
        {"GroupId", m_connector.m_group_id},
        {"ChassisId", m_connector.m_chassis_id},
        {"ManagerId", m_connector.m_manager_id},
        {"Container", m_connector.m_container},
        {"SilkText", m_connector.m_silk_text}};

    // 定义占位符替换的lambda函数
    auto replace_string_placeholders = [&placeholder_map](const std::string& input) -> std::string {
        return mc::fmt::format_dict(input, placeholder_map);
    };

    // 递归处理variant的lambda函数
    std::function<mc::variant(const mc::variant&)> process_variant;
    process_variant = [&](const mc::variant& input) -> mc::variant {
        if (input.is_string()) {
            return replace_string_placeholders(input.get_string());
        } else if (input.is_dict()) {
            mc::mutable_dict result;
            const auto&      dict = input.get_object();
            for (auto it = dict.begin(); it != dict.end(); ++it) {
                std::string processed_key = replace_string_placeholders(it->key.as<std::string>());
                mc::variant processed_value = process_variant(it->value);
                result.insert(processed_key, processed_value);
            }
            return result;
        } else if (input.is_array()) {
            std::vector<mc::variant> processed_array;
            const auto&              array = input.get_array();
            for (const auto& item : array) {
                processed_array.push_back(process_variant(item));
            }
            return processed_array;
        }

        // 对于其他类型，直接返回原值
        return input;
    };

    // 处理所有objects
    for (auto it = m_objects.begin(); it != m_objects.end(); ++it) {
        std::string processed_key   = replace_string_placeholders(it->key.as<std::string>());
        mc::variant processed_value = process_variant(it->value);
        processed_objects.insert(processed_key, processed_value);
    }

    m_objects = std::move(processed_objects);
}

mc::mutable_dict device_csr::process_function_args(const func& func_obj) {
    mc::mutable_dict processed_args;
    for (const auto& arg : func_obj.get_args()) {
        std::string arg_value = arg.value.as<std::string>();

        if (arg_value.substr(0, 3) == "<=/") {
            auto sync_prop = func_parser::get_instance().parse_sync_property(arg_value);
            processed_args.insert(arg.key, sync_prop);
        } else if (arg_value.substr(0, 2) == "#/") {
            auto ref_prop = func_parser::get_instance().parse_ref_property(arg_value);
            processed_args.insert(arg.key, ref_prop);
        } else {
            processed_args.insert(arg.key, arg.value);
        }
    }
    return processed_args;
}

void device_csr::init_functions(mc::engine::service* service) {
    mc::mutable_dict functions;
    for (auto it = m_objects.begin(); it != m_objects.end(); ++it) {
        if (!is_function_object(it->key.as<std::string>())) {
            continue;
        }

        func func_obj = it->value.as<func>();
        func_obj.set_args(process_function_args(func_obj));
        functions[it->key.as<std::string>()] = func_obj;
    }
    // 将service指针转换为shared_ptr，使用不增加引用计数的方式
    auto service_ptr = std::shared_ptr<mc::engine::service>(service, [](mc::engine::service*) {
    });
    func_collection::get_instance().add(m_connector.m_position, service_ptr, functions);
}

void device_csr::init(const mc::variant& csr, mc::dict connector) {
    mc::from_variant(csr, *this);
    mc::from_variant(connector, m_connector);

    // position 不会通过csr初始化，手动初始化成 group_position
    m_connector.m_position = m_connector.m_group_position;

    validate_csr();

    m_original_connector = std::move(connector);

    // 统一对所有objects进行占位符替换
    process_objects_placeholders();
}

mc::engine::abstract_object* device_csr::find_parent_object(mc::engine::service* service,
                                                            mc::dict&            object) {
    auto& table = service->get_object_table();
    if (object.find("@Parent") != object.end()) {
        std::string parent_name =
            object["@Parent"].as<std::string>() + "_" + m_connector.m_position;
        auto parent = table.find_object(mc::engine::by_object_name::field == parent_name).get();
        if (parent == nullptr) {
            MC_THROW(mc::parse_error_exception, "Parent object not found: ${name}",
                     ("name", parent_name));
        }
        return static_cast<mc::engine::abstract_object*>(parent);
    } else {
        std::string parent_name = m_unit.m_name + "_" + m_connector.m_position;
        auto parent = table.find_object(mc::engine::by_object_name::field == parent_name).get();
        if (parent == nullptr) {
            parent = table.find_object(mc::engine::by_object_name::field == "Devmon").get();
            if (parent == nullptr) {
                MC_THROW(mc::parse_error_exception, "Devmon object not found");
            }
        }
        return static_cast<mc::engine::abstract_object*>(parent);
    }
}

void device_csr::create_child_device(mc::engine::service*             service,
                                     std::shared_ptr<device_driver_t> device) {
    // 使用临时存储需要删除的对象名称，避免在迭代过程中修改集合
    std::vector<std::string> objects_to_erase;

    for (auto it = m_objects.begin(); it != m_objects.end(); ++it) {
        std::string object_name = it->key.as<std::string>() + "_" + m_connector.m_position;

        auto device_name = object_name.substr(0, object_name.find_first_of("_"));
        if (device_name != device->device_name) {
            continue;
        }
        mc::mutable_dict csr_object = it->value.as<mc::dict>();

        ilog("create child device ${name}", ("name", object_name));
        auto device_object =
            static_cast<mc::engine::abstract_object*>(device->ctor(service, object_name.c_str()));
        device_object->set_position(m_connector.m_position);
        device_object->set_parent(find_parent_object(service, csr_object));
        csr_object["SystemId"] = m_connector.m_system_id; // child设备添加SystemId属性,用于生成path
        device->init(device_object, &csr_object, &m_original_connector);
        service->register_object(device_object);
        object_group_data::get_instance().save_device_object(device_object, m_connector.m_position,
                                                             object_name);
        ilog("create child device ${name} success", ("name", object_name));

        objects_to_erase.push_back(it->key.as<std::string>());
    }

    for (const auto& name : objects_to_erase) {
        m_objects.erase(name);
    }
}

void device_csr::create_childs_device(mc::engine::service* service, device_driver& drv) {
    std::string& component_device_name = m_unit.m_type;
    for (const auto& device : drv.get_devices()) {
        if (device->device_name != component_device_name) {
            create_child_device(service, device);
        }
    }
}

mc::engine::abstract_object* device_csr::create_component_device(mc::engine::service* service,
                                                                 device_driver&       drv) {
    std::string& device_name = m_unit.m_type;                                // 部件设备类名称
    std::string  object_name = m_unit.m_name + "_" + m_connector.m_position; // 部件设备对象名称
    if (!m_objects.contains(m_unit.m_name)) {
        MC_THROW(mc::parse_error_exception, "unit object not found in csr: ${name}",
                 ("name", m_unit.m_name));
    }
    mc::mutable_dict csr_object = m_objects[m_unit.m_name].as<mc::mutable_dict>();

    ilog("create device ${name}", ("name", object_name));
    device_driver_t& device = drv.get_device(device_name);
    auto             device_object =
        static_cast<mc::engine::abstract_object*>(device.ctor(service, object_name.c_str()));
    device_object->set_position(m_connector.m_position);
    auto parent = find_parent_object(service, csr_object);
    device_object->set_parent(parent);
    csr_object["SystemId"] = m_connector.m_system_id; // 部件主设备添加SystemId属性,用于生成path
    device.init(device_object, &csr_object, &m_original_connector);
    service->register_object(device_object);
    object_group_data::get_instance().save_device_object(device_object, m_connector.m_position,
                                                         object_name);
    ilog("create device ${name} success", ("name", object_name));

    m_objects.erase(m_unit.m_name);
    return device_object;
}

void device_csr::create_common_devices(mc::engine::service* service) {
    auto& object_group_instance = object_group_data::get_instance();
    for (auto it = m_objects.begin(); it != m_objects.end(); ++it) {
        std::string object_name = it->key.as<std::string>() + "_" + m_connector.m_position;
        mc::dict    csr_object  = it->value.as<mc::dict>();

        std::string    device_name = object_name.substr(0, object_name.find_first_of("_"));
        std::string    parent_name = m_unit.m_name + "_" + m_connector.m_position;
        device_driver* drv         = nullptr;
        try {
            drv = &device_driver_factory::get_instance().get_device_driver(device_name);
        } catch (const mc::invalid_arg_exception& e) {
            continue;
        }

        device_driver_t& device = drv->get_device(device_name);
        auto             device_object =
            static_cast<mc::engine::abstract_object*>(device.ctor(service, object_name.c_str()));
        device_object->set_position(m_connector.m_position);
        auto parent = find_parent_object(service, csr_object);

        device_object->set_parent(parent);
        device.init(device_object, &csr_object, &m_original_connector);
        service->register_object(device_object);
        object_group_instance.save_device_object(device_object, m_connector.m_position,
                                                 object_name);
        ilog("create device ${name} success", ("name", object_name));
    }
}

std::pair<mc::engine::abstract_object*, device_driver*>
device_csr::create_devices_object(mc::engine::service* service) {
    object_group_data::get_instance().clear_device_objects(m_connector.m_position);
    init_functions(service);
    device_driver& drv           = m_unit.load_compatible_driver();
    auto           device_object = create_component_device(service, drv);

    return std::make_pair(device_object, &drv);
}

void device_csr::finalize_device_setup(mc::engine::service*         service,
                                       mc::engine::abstract_object* device_object,
                                       device_driver&               drv) {
    // 创建子设备和通用设备
    create_childs_device(service, drv);
    create_common_devices(service);

    // 启动设备业务
    if (device_object != nullptr) {
        device_driver_t& device = drv.get_device(m_unit.m_type);
        device.start(device_object);
    }
}

mc::dict device_csr::get_processed_objects() const {
    return m_objects;
}

} // namespace devmon

MC_REFLECT(devmon::unit, ((m_type, "Type"))((m_name, "Name"))((m_compatible, "Compatible")));
MC_REFLECT(devmon::connector,
           ((m_system_id, "SystemId"))((m_position, "Position"))((m_slot, "Slot"))(
               (m_buses, "Buses"))((m_group_position, "GroupPosition"))((m_group_id, "GroupId"))(
               (m_chassis_id, "ChassisId"))((m_manager_id, "ManagerId"))(
               (m_container, "Container"))((m_silk_text, "SilkText")));
MC_REFLECT(devmon::device_csr,
           ((m_unit, "Unit"))((m_objects, "Objects"))((m_topology, "ManagementTopology")));
